home *** CD-ROM | disk | FTP | other *** search
- /* SPECTRUM.C - Displays Specrum of Given Signal (Data)
- *
- * Copyright (C) 1988, 1989 by J Vuori. All rights reserved.
- * Author(s): J Vuori
- * Modification(s):
- */
-
- #define NOMINMAX // because they are defined in stdlib.h
- #include <windows.h>
- #include <math.h>
- #include <stdlib.h>
- #include <memory.h>
- #include <string.h>
- #include "music.h"
- #include "fft.h"
-
- /* parameters */
- #define WINDOW_CLASS "spectrum"
- #define FFTLOGLEN 8
- #define VERTICALTICKS 5
- #define HORISONTALTICKS 4
-
- /* internal contants */
- #define FFTLEN (1 << FFTLOGLEN)
- #define DATAPROP "hData" /* id names of window properties */
- #define TRANSFORMEDPROP "hXformed"
- #define SELECTIONPROP "hSelect"
- #define IDMPRINTSPECTRUM 10 /* menu id's */
- #define IDMNONE 11
- #define IDMHANNING 12
- #define IDMHAMMING 13
- #define IDMBLACKMAN 14
-
-
- long FAR PASCAL SpectrumProc(HWND, unsigned, WORD, LONG);
-
- /* Initialize Spectrum Analyzer */
- BOOL SpectrumInit(hInstance)
- HANDLE hInstance;
- {
- WNDCLASS wcClass;
-
- wcClass.hCursor = LoadCursor(NULL, IDC_ARROW);
- wcClass.hIcon = 0;
- wcClass.lpszMenuName = (LPSTR) 0;
- wcClass.lpszClassName = (LPSTR) WINDOW_CLASS;
- wcClass.hbrBackground = GetStockObject(WHITE_BRUSH);
- wcClass.hInstance = hInstance;
- wcClass.style = CS_VREDRAW | CS_HREDRAW;
- wcClass.lpfnWndProc = SpectrumProc;
- wcClass.cbClsExtra = 0;
- wcClass.cbWndExtra = 0;
- if (!RegisterClass((LPWNDCLASS) &wcClass))
- return FALSE;
-
- return TRUE;
- }
-
-
- /* Activate Spectrum Analyzer */
- BOOL Spectrum(hWnd, Name, pprocSource)
- HWND hWnd;
- char *Name;
- double (*pprocSource)(unsigned);
- {
- HMENU hMenuMain, hMenuPopup;
- HWND hWndSpectrum, hWndPrev;
- HDC hDC;
- TEXTMETRIC tmFontInfo;
- RECT rcWnd;
- HANDLE hOrigData, hXformed;
- int X, Y, height, lenght;
-
- /* check if there are already display of the same source */
- if(hWndSpectrum = FindWindow((LPSTR) WINDOW_CLASS, (LPSTR) Name))
- {
- /* yes, update it only */
- hOrigData = GetProp(hWndSpectrum, (LPSTR) DATAPROP);
- hXformed = GetProp(hWndSpectrum, (LPSTR) TRANSFORMEDPROP);
- FetchData(hOrigData, pprocSource);
- TransformData(hWndSpectrum, hOrigData, hXformed);
- InvalidateRect(hWndSpectrum, (LPRECT) NULL, TRUE);
- } else
- {
- /* no, create a new one */
- /* first allocate memory for local usage */
- if(!(hOrigData = LocalAlloc(LMEM_MOVEABLE, FFTLEN * sizeof(double))))
- return FALSE;
- if(!(hXformed = LocalAlloc(LMEM_MOVEABLE, FFTLEN * sizeof(struct complex))))
- {
- LocalFree(hOrigData);
- return FALSE;
- }
-
- /* create menu */
- hMenuMain = CreateMenu();
- ChangeMenu(hMenuMain, NULL, (LPSTR) "Print", IDMPRINTSPECTRUM, MF_APPEND);
-
- hMenuPopup = CreateMenu();
- ChangeMenu(hMenuPopup, NULL, (LPSTR) "None", IDMNONE, MF_APPEND);
- ChangeMenu(hMenuPopup, NULL, (LPSTR) "Hanning", IDMHANNING, MF_APPEND);
- ChangeMenu(hMenuPopup, NULL, (LPSTR) "Hamming", IDMHAMMING, MF_APPEND);
- ChangeMenu(hMenuPopup, NULL, (LPSTR) "Blackman", IDMBLACKMAN, MF_APPEND);
-
- ChangeMenu(hMenuMain, NULL, (LPSTR) "Windows", hMenuPopup, MF_APPEND | MF_BYCOMMAND | MF_POPUP);
-
- /* calculate windows dimensions */
- hDC = GetDC(NULL);
- GetTextMetrics(hDC, (LPTEXTMETRIC) &tmFontInfo);
- ReleaseDC(NULL, hDC);
-
- /* analyze where to put it */
- if(hWndPrev = FindWindow((LPSTR) WINDOW_CLASS, (LPSTR) NULL))
- {
- /* there are previous windows, stack it on the top of them */
- GetWindowRect(hWndPrev, (LPRECT) &rcWnd);
- height = rcWnd.bottom - rcWnd.top;
- lenght = rcWnd.right - rcWnd.left;
-
- X = rcWnd.left + GetSystemMetrics(SM_CXVSCROLL);
- Y = rcWnd.top + GetSystemMetrics(SM_CYHSCROLL);
- } else
- {
- /* it is first window (of its class) put it to the right of parent window */
- GetWindowRect(hWnd, (LPRECT) &rcWnd);
- height = 14 * tmFontInfo.tmHeight;
- lenght = 30 * tmFontInfo.tmAveCharWidth;
-
- X = rcWnd.right + GetSystemMetrics(SM_CXVSCROLL);
- Y = rcWnd.top + (rcWnd.bottom - rcWnd.top) / 2 - height / 2;
- }
-
- /* create window to center of parent window */
- hWndSpectrum = CreateWindow(
- (LPSTR) WINDOW_CLASS, /* window class name */
- (LPSTR) Name, /* name appearing in window caption */
- WS_SIZEBOX | WS_CAPTION |
- WS_SYSMENU | WS_POPUP, /* style */
- X, /* x : ignored for tiled window */
- Y, /* y : ignored for tiled window */
- lenght, /* cx : ignored for tiled window */
- height, /* cy : ignored for tiled window */
- hWnd, /* parent window */
- hMenuMain, /* menu, or child window id */
- (HANDLE)hInstMusic, /* handle to window instance */
- (LPSTR) NULL /* params to pass on */
- );
-
- /* set datawindow selection to deterministic state */
- InitializeSelection(hWndSpectrum);
-
- /* get data from source and put handle to windows context */
- FetchData(hOrigData, pprocSource);
- TransformData(hWndSpectrum, hOrigData, hXformed);
- SetProp(hWndSpectrum, (LPSTR) DATAPROP, hOrigData);
- SetProp(hWndSpectrum, (LPSTR) TRANSFORMEDPROP, hXformed);
-
- /* display edit control */
- ShowWindow(hWndSpectrum, SHOW_OPENWINDOW);
- }
-
- UpdateWindow(hWndSpectrum);
-
- return (TRUE);
- }
-
-
- /* Spectrum Class Procedure */
- long FAR PASCAL SpectrumProc(hWnd, message, wParam, lParam)
- HWND hWnd;
- unsigned message;
- WORD wParam;
- LONG lParam;
- {
- PAINTSTRUCT ps;
-
- switch (message)
- {
- case WM_COMMAND:
- SpectrumCommand(hWnd, wParam);
- break;
-
- case WM_PAINT:
- BeginPaint(hWnd, (LPPAINTSTRUCT) &ps);
- DrawSpectrum(hWnd, ps.hdc);
- ValidateRect(hWnd, (LPRECT) NULL);
- EndPaint(hWnd, (LPPAINTSTRUCT) &ps);
- break;
-
- case WM_MOUSEMOVE:
- ChkCursor();
- break;
-
- case WM_CLOSE:
- DeleteSpectrumProps(hWnd);
- break;
-
- default:
- return((long)DefWindowProc(hWnd, message, wParam, lParam));
- break;
- }
-
- return(0L);
- }
-
-
- /* initialize menu selections */
- static InitializeSelection(hWnd)
- HWND hWnd;
- {
- HANDLE hSelection;
- int *pSelection;
-
- /* set menu selection */
- hSelection = LocalAlloc(LMEM_MOVEABLE, sizeof(int));
- pSelection = (int *) LocalLock(hSelection);
- *pSelection = 0;
- CheckMenuItem(GetMenu(hWnd), IDMNONE+0, MF_CHECKED);
- LocalUnlock(hSelection);
- SetProp(hWnd, (LPSTR) SELECTIONPROP, hSelection);
- }
-
- /* get data from source */
- static FetchData(hPropData, pprocSource)
- HANDLE hPropData;
- double (*pprocSource)(unsigned);
- {
- double *p;
- register unsigned i;
-
- p = (double *) LocalLock(hPropData);
-
- /* get data from source */
- Waiting();
- for(i = 0; i < FFTLEN; i++)
- *p++ = (*pprocSource) (i);
- Ready();
-
- LocalUnlock(hPropData);
- }
-
-
- /* modify data with window, then fourier transform it */
- static TransformData(hWnd, hPropData, hXformData)
- HWND hWnd;
- HANDLE hPropData, hXformData;
- {
- struct complex *pData;
- double *pOrig;
-
- pOrig = (double *) LocalLock(hPropData);
- pData = (struct complex *) LocalLock(hXformData);
-
- Waiting();
- FFTWindow(hWnd, pData, pOrig, FFTLOGLEN);
- fft(pData, FFTLOGLEN);
- Ready();
-
- LocalUnlock(hXformData);
- LocalUnlock(hPropData);
- }
-
-
- /* initialize printing */
- int PrintInit(hWnd, hDC, s)
- HWND hWnd;
- HDC hDC;
- char *s;
- {
- POINT ptPageSize;
-
- /* display spectrum as 4/5, 1/3 of original size */
- SetMapMode(hDC, MM_ANISOTROPIC);
-
- SetWindowOrg(hDC, -75, 115);
- SetWindowExt(hDC, 607, -130);
-
- Escape(hDC, GETPHYSPAGESIZE, 0, (LPSTR) NULL, (LPSTR) &ptPageSize);
-
- SetViewportOrg(hDC, 0, 0);
- SetViewportExt(hDC, 4 * ptPageSize.x / 5, 1 * ptPageSize.y / 3);
-
- strcpy(s, "FFT Spectrum");
- return(1); /* only one page */
- }
-
-
- /* print one (and only) page */
- void PrintPage(hWnd, hDC, PageCnt)
- HWND hWnd;
- HDC hDC;
- int PageCnt;
- {
- HANDLE hXformed;
- LONG TextExt;
- struct complex *pData;
- double MaxValue;
- char buff[32];
-
- hXformed = GetProp(hWnd, (LPSTR) TRANSFORMEDPROP);
- pData = (struct complex *) LocalLock(hXformed);
-
- SetWindowOrg(hDC, -75, 115);
- SetWindowExt(hDC, 607, -130);
-
- MaxValue = DetermineMaxValue(pData, FFTLOGLEN);
- DrawAxes(hDC, MaxValue);
- DrawValues(hDC, pData, MaxValue);
-
- /* Write Spectrums Name */
- GetWindowText(hWnd, (LPSTR) buff, sizeof(buff));
- TextExt = GetTextExtent(hDC, (LPSTR) buff, strlen(buff));
- TextOut(hDC, (512 - LOWORD(TextExt)) / 2, 110, (LPSTR) buff, strlen(buff));
-
- LocalUnlock(hXformed);
- }
-
-
- /* do menu command */
- static SpectrumCommand(hWnd, wParam)
- HWND hWnd;
- WORD wParam;
- {
- HANDLE hSelection;
- int *pSelection;
-
- switch (wParam)
- {
- case IDMPRINTSPECTRUM:
- Waiting();
- PrintIt(hWnd, PrintInit, PrintPage);
- Ready();
- break;
-
- case IDMNONE:
- case IDMHAMMING:
- case IDMHANNING:
- case IDMBLACKMAN:
- hSelection = GetProp(hWnd, (LPSTR) SELECTIONPROP);
- pSelection = (int *) LocalLock(hSelection);
-
- if(wParam-IDMNONE != *pSelection)
- {
- /* change selection */
- CheckMenuItem(GetMenu(hWnd), IDMNONE + *pSelection, MF_UNCHECKED);
- CheckMenuItem(GetMenu(hWnd), wParam, MF_CHECKED);
- *pSelection = wParam-IDMNONE;
-
- /* transfrom it */
- TransformData(hWnd, GetProp(hWnd, (LPSTR) DATAPROP), GetProp(hWnd, (LPSTR) TRANSFORMEDPROP));
- InvalidateRect(hWnd, (LPRECT) NULL, TRUE);
- }
-
- LocalUnlock(hSelection);
- break;
-
- default:
- break;
- }
- }
-
-
- /* free any local window properties */
- static DeleteSpectrumProps(hWnd)
- HWND hWnd;
- {
- LocalFree(GetProp(hWnd, (LPSTR) DATAPROP)); RemoveProp(hWnd, (LPSTR) DATAPROP);
- LocalFree(GetProp(hWnd, (LPSTR) TRANSFORMEDPROP)); RemoveProp(hWnd, (LPSTR) TRANSFORMEDPROP);
- LocalFree(GetProp(hWnd, (LPSTR) SELECTIONPROP)); RemoveProp(hWnd, (LPSTR) SELECTIONPROP);
-
- DestroyWindow(hWnd);
- }
-
-
- /* print spectrum to window */
- static DrawSpectrum(hWnd, hDC)
- HWND hWnd;
- HDC hDC;
- {
- HANDLE hXformed;
- RECT rcClient;
- struct complex *pData;
- double MaxValue;
-
- hXformed = GetProp(hWnd, (LPSTR) TRANSFORMEDPROP);
- pData = (struct complex *) LocalLock(hXformed);
-
- SetMapMode(hDC, MM_ANISOTROPIC);
-
- SetWindowOrg(hDC, -75, 115);
- SetWindowExt(hDC, 607, -130);
-
- GetClientRect(hWnd, (LPRECT) &rcClient);
- SetViewportOrg(hDC, 0, 0);
- SetViewportExt(hDC, rcClient.right, rcClient.bottom);
-
- MaxValue = DetermineMaxValue(pData, FFTLOGLEN);
- DrawAxes(hDC, MaxValue);
- DrawValues(hDC, pData, MaxValue);
-
- LocalUnlock(hXformed);
- }
-
-
- /* adujust current front in hDC so that string s fits in cx,cy rectangle */
- static HANDLE AdjustFont(hDC, s, cx, cy)
- HDC hDC;
- char *s;
- int cx, cy;
- {
- TEXTMETRIC tmFontInfo;
- LOGFONT lfNewFont;
- LONG TextExt;
- BOOL fChange;
-
- GetTextMetrics(hDC, (LPTEXTMETRIC) &tmFontInfo);
- memset(&lfNewFont, 0, sizeof(LOGFONT));
- lfNewFont.lfHeight = tmFontInfo.tmHeight;
- lfNewFont.lfWidth = tmFontInfo.tmAveCharWidth;
-
- TextExt = GetTextExtent(hDC, (LPSTR) s, strlen(s));
- if (abs(LOWORD(TextExt) - cx) > cx/10)
- {
- lfNewFont.lfWidth = cx * lfNewFont.lfWidth / LOWORD(TextExt);
- fChange = TRUE;
- }
- if (abs(HIWORD(TextExt) - cy) > cy/10)
- {
- lfNewFont.lfHeight = cy * lfNewFont.lfHeight / HIWORD(TextExt);
- fChange = TRUE;
- }
-
- return(fChange ? CreateFontIndirect((LPLOGFONT) &lfNewFont) : NULL);
- }
-
-
- /* draw co-oordinate axes */
- static DrawAxes(hDC, MaxValue)
- HDC hDC;
- double MaxValue;
- {
- HANDLE hOldFont, hNewFont;
- LONG TextExt;
- register int x, y;
- char buff[16];
-
- /* draw axes lines */
- MoveTo(hDC, 0, 100);
- LineTo(hDC, 0, 0);
- LineTo(hDC, 512, 0);
-
- /* check if there are need for smaller font */
- if(hNewFont = AdjustFont(hDC, "XXXXX.X", 75, 15))
- hOldFont = SelectObject(hDC, hNewFont);
-
- /* draw vertical axe with value ticks & labels */
- for(y = 0; y <= 100; y += 100/VERTICALTICKS)
- {
- MoveTo(hDC, -5, y); LineTo(hDC, 0, y);
- sprintf(buff, "%.1lf", (double) y / 100.0 * MaxValue);
- TextExt = GetTextExtent(hDC, (LPSTR) buff, strlen(buff));
- TextOut(hDC, -10-LOWORD(TextExt), y+HIWORD(TextExt)/2, (LPSTR) buff, strlen(buff));
- }
-
- /* draw horisontal axe with value ticks & labels */
- for(x = 0; x <= 512; x += 512/HORISONTALTICKS)
- {
- MoveTo(hDC, x, -2); LineTo(hDC, x, 0);
- sprintf(buff, "%.02lf", (double) x / 512.0);
- TextExt = GetTextExtent(hDC, (LPSTR) buff, strlen(buff));
- TextOut(hDC, x - LOWORD(TextExt)/2, -4, (LPSTR) buff, strlen(buff));
- }
-
- /* return original font */
- if(hNewFont)
- {
- SelectObject(hDC, hOldFont);
- DeleteObject(hNewFont);
- }
- }
-
-
- /* draw spectrum plot */
- static DrawValues(hDC, pData, MaxValue)
- HDC hDC;
- struct complex pData[];
- double MaxValue;
- {
- HPEN hPen, hOldPen;
- register int i;
-
- /* create wider pen */
- hPen = CreatePen(0, 4, GetTextColor(hDC));
- hOldPen = SelectObject(hDC, hPen);
-
- /* draw datas */
- MoveTo(hDC, 0, (int) (cabs(pData[Bit_Reverse(0, FFTLOGLEN)]) / MaxValue * 100.0));
- for(i = 1; i < FFTLEN / 2; i++)
- LineTo(hDC, i * 4, (int) (cabs(pData[Bit_Reverse(i, FFTLOGLEN)]) / MaxValue * 100.0));
-
- /* restore old pen */
- SelectObject(hDC, hOldPen);
- DeleteObject(hPen);
- }
-
-
- /* filters data with special windows to resolve discontinuites */
- static FFTWindow(hWnd, dest, src, m)
- HWND hWnd;
- struct complex *dest;
- double *src;
- int m;
- {
- HANDLE hSelection;
- int *pSelection;
- static void (*WindowFunctions[]) (struct complex *, double *, int) =
- {
- DirectWin,
- HanningWin,
- HammingWin,
- BlackmanWin
- };
-
- hSelection = GetProp(hWnd, (LPSTR) SELECTIONPROP);
- pSelection = (int *) LocalLock(hSelection);
-
- (*WindowFunctions[*pSelection])(dest, src, m);
-
- LocalUnlock(hSelection);
- }
-